package org.mathcat.netty.http;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.ServerChannel;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;

/**
 * [TITLE]
 * <p>[DESCRIPTION]</p>
 * <p>Created by xuweinan on 2018/7/16</p>
 *
 * @author xuweinan
 */
public class HttpServer {
    private final int port;

    private HttpServer(int port) {
        this.port = port;
    }

    public static void main(String[] args) throws Exception {
        int port;
        if (args.length != 1) {
            port = 8080;
        } else {
            port = Integer.parseInt(args[0]);
        }
        new HttpServer(port).start();
    }

    private void start() throws Exception {
        ServerBootstrap bootstrap = new ServerBootstrap();
        boolean isLinux = System.getProperty("os.name").toLowerCase().contains("linux");
        EventLoopGroup group = isLinux ? new EpollEventLoopGroup() : new NioEventLoopGroup();
        Class<? extends ServerChannel> channelClass = isLinux ? EpollServerSocketChannel.class : NioServerSocketChannel.class;
        bootstrap.group(group).channel(channelClass)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch) {
                        System.out.println("initChannel ch:" + ch);
                        ch.pipeline()
                                .addLast("decoder", new HttpRequestDecoder())   // 1 request解码器
                                .addLast("encoder", new HttpResponseEncoder())  // 2 response编码器
                                // 3 消息聚合器，很重要。 为什么能有FullHttpRequest这个东西，就是因为有他，HttpObjectAggregator，如果没有他，就不会有那个消息是FullHttpRequest的那段Channel，同样也不会有FullHttpResponse
                                .addLast("aggregator", new HttpObjectAggregator(512 * 1024))
                                .addLast("handler", new HttpHandler());        // 4
                    }
                })
                .option(ChannelOption.SO_BACKLOG, 128) // determining the number of connections queued
                .childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE);

        bootstrap.bind(port).sync();
    }
}
